home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / BODI / TWCMD.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-10  |  35.4 KB  |  1,562 lines

  1. /*
  2.     This module handles the Text Window commands
  3. */
  4. /************************************************************************/
  5. /* HISTORY                                */
  6. /*                                     */
  7. /* 11/07/89  -  Replace all scale_iv() with scaler()            */
  8. /*        TWslider_chk()  -   "      "           "                */
  9. /*        TWsliderH()    -   "      "           "         */
  10. /*        TWhslide()    -   "      "           "        */
  11. /************************************************************************/
  12. #include    "gemdefs.h"
  13. #include    <obdefs.h>
  14. #include    "defs.h"
  15. #include    "keys.h"
  16. #include    "dbase.h"
  17. #include    "deskset2.h"
  18.  
  19. #define        MIN_LEFT    10    /* minimum edit space left    */
  20. #define        MIN_FREE    80L    /* minimum editing space    */
  21. #define        BLTAG        17    /* beginning Local Tag number    */
  22. #define        NUMTAG        200    /* total number of Tags...    */
  23.  
  24. extern    int        txt_handle;        /* TWindow handle    */
  25. extern    GRECT        twork;            /* TWindow work area    */
  26. extern    int        gl_hchar;        /* Text char height    */
  27. extern    int        gl_wchar;        /* Text char width    */
  28. extern    int        *gcurx;            /* Ptr to mouse x    */
  29. extern    int        *gcury;            /* Ptr to mouse y    */
  30. extern    int        msg_buff[];        /* evnt_multi buffer    */
  31. extern    int        gl_apid;        /* ID for appl_write    */
  32. extern    REGION        *gl_region_ptr;        /* current Region Ptr    */
  33. extern    int        force_draw_flag;    /* Force redraw on Prev    */
  34. extern    OBJECT        *ad_menu;        /* OBJECT for menu bar    */
  35. extern    int        BSTATE;            /* Button State...    */
  36. extern    char        *get_edit();
  37.  
  38. extern    char        nuls[];            /* null string (GOG)    */
  39. extern    unsigned char    *setwptr(), *skiptag(), *malloc(), *toeofline();
  40. extern    unsigned char    mapkbd(), getfp(), toupper(), getLch();
  41. extern    int        rewrite_line(), wdw_eol();
  42. extern    unsigned    cb_size;        /* Copy buffer size    */
  43. extern    int        TWhclip;        /* TWindow horiz. clip    */
  44. extern    unsigned char    *prvp1(), *prvp2();
  45.  
  46. static    unsigned char    *last_one;        /* last match pointer    */
  47. static    unsigned char    lkey;            /* last        cmd key    */
  48. static    unsigned char    ckey;            /* current    cmd key    */
  49. static    unsigned char    last_again    = 0;    /* Last Again command    */
  50. static    unsigned char    search_stg [52]    = {0};    /* Search    String    */
  51. static    unsigned char    replace_stg[52] = {0};    /* Replace    String    */
  52. static    char        Ins_Tag        = 0;    /* in Insert Tag mode    */
  53. static    int        inIOm        = 1;    /* Editor Ins/OvW flag    */
  54. static    unsigned char    mrkfbrk;        /* Mark fctN break char */
  55.  
  56. ARTICLE        *TWart_ptr    = (ARTICLE *)0;    /* TW current article    */
  57. char        TWaltered    = 0;        /* TWindow altered flag    */
  58. unsigned char    **upd_ptr    = (char **)0;    /* region ptr tag array    */
  59. int        upd_tags;            /* # of ptrs in array    */
  60. int        mrkfctN        = 0;        /* current Mark functN    */
  61. int        last_tag    = BLTAG;    /* Last used Local Tag    */
  62. int        TWVSLpos    = 0;        /* TW VSlider position    */
  63. int        TWVSLsize    = 1000;        /* TW VSlider size    */
  64.  
  65. /*
  66.     Text Window arrow function handler
  67. */
  68. TW_arrow(action)
  69. int    action;
  70. {
  71.     int    hmove;
  72.  
  73.     if (!TWart_ptr)
  74.         return;
  75.     switch(action) {
  76.     case WA_UPPAGE:  
  77.         pageup_cmd();
  78.         break;
  79.     case WA_DNPAGE: 
  80.         pagedown_cmd();
  81.         break;
  82.     case WA_UPLINE:
  83.         up_cmd(current.row + 1);
  84.         break;
  85.     case WA_DNLINE:
  86.         down_cmd(current.mrow - current.row);
  87.         break;
  88.     case WA_LFPAGE:
  89.         hmove = (TWhclip > current.mcol) ? current.mcol:TWhclip;
  90.         goto toL;
  91.     case WA_RTPAGE:
  92.         hmove = current.mcol;
  93.         goto toR;
  94.     case WA_LFLINE:
  95.         hmove = 1;
  96. toL:        if (TWhclip)
  97.             left_cmd(current.col + hmove);
  98.         break;
  99.     case WA_RTLINE:
  100.         hmove = 1;
  101. toR:        if (current.mcol < wdw_cols)
  102.             TWmoveRight(TWhclip + hmove,hmove);
  103.         break;
  104.     }
  105. }
  106.  
  107. /*
  108.     Text Window mouse button handler
  109. */
  110. TW_button()
  111. {
  112.     int    xcur, ycur, maxcol;
  113.     int    xdiff, ydiff;
  114.     unsigned tagn;
  115.  
  116.     if (!TWart_ptr || !xyinTW(*gcurx,*gcury))
  117.         return(0);
  118.     xcur    = *gcurx - (twork.g_x + gl_wchar);
  119.     if (xcur < 0)
  120.         return(0);
  121.     xcur    /= gl_wchar;
  122.     ycur    = *gcury - twork.g_y;
  123.     ycur    /= gl_hchar;
  124.     if (ydiff = abs(current.row - ycur)) {    /* check move y first    */
  125.         if (current.row > ycur) {
  126.             if (free_start != buf_start)
  127.                 backup(ydiff);
  128.             else    ydiff = 0;
  129.         }
  130.         else {
  131.             if (current_char != buf_end)
  132.                 forup(ydiff);
  133.             else    ydiff = 0;
  134.         }
  135.     }
  136.     maxcol = nchartoEline();        /* ultimate line column    */
  137.     if (ydiff) {                /* if y been moved...    */
  138.         if (maxcol) {
  139.             xdiff    = TWhclip + xcur;
  140.             right_cmd(xdiff > maxcol ? maxcol:xdiff);
  141.         }
  142.         else    nscr(0);
  143.     }
  144.     else
  145.     if (xdiff = abs(current.col - xcur)) {    /* move x only on line    */
  146.         if (current.col > xcur)
  147.             left_cmd(xdiff);
  148.         else    right_cmd(xdiff > maxcol ? maxcol:xdiff);
  149.     }
  150.     if (mrkfctN) {
  151.         if (BSTATE == 2) {
  152.             ckey = mrkfbrk;
  153.             return(1);
  154.         }
  155.     }
  156.     else
  157.     if (!Ins_Tag) {
  158.       if (ptagc(*current_char))        /* if cursor at Pi TAG    */
  159.         PiTag_cmd(*(current_char + 1));
  160.       else
  161.       if (ctagc(*current_char)) {        /* or cursor at Cp TAG    */
  162.         tagn = *(current_char + 1) + 1;
  163. /*        if (tagn >= BLTAG)
  164.             last_tag = tagn;    */
  165.         do_tag(tagn,0);
  166.       }
  167.     }
  168.     return(0);
  169. }
  170.  
  171. /*
  172.     Text Window Top menu handler
  173. */
  174. TW_menu(item)
  175. int    item;
  176. {
  177.     menu_tnormal(ad_menu,TEXT,1);
  178.     switch(item) {
  179.     case SELART:    ckey = ATS;    break;
  180.     case GETXT:    ckey = ATG;    break;
  181.     case DELTXT:    ckey = ATD;    break;
  182.     case BUFTXT:    ckey = ATB;    break;
  183.     case CPYTXT:    ckey = ATC;    break;
  184.     case FORFIND:    ckey = ATF;    break;
  185.     case REVFIND:    ckey = ATV;    break;
  186.     case RPLC:    ckey = ATR;    break;
  187.     case SETMARK:    ckey = ATM;    break;
  188.     case JPMARK:    ckey = ATJ;    break;
  189.     case INSTAG:    ckey = ATT;    break;
  190.     case INSLTAG:    ckey = ATL;    break;
  191.     case DELTAG:    ckey = ATX;    break;
  192.     }
  193.     return(TW_Cmds());
  194. }
  195.  
  196. /*
  197.     Function to process Text window Keyboard commands
  198.     for Cursor/Text/File scrolling and single character
  199.     deletion.
  200. */
  201. TW_Keys()
  202. {
  203.     int    found = true;
  204.  
  205.     if (!TWart_ptr)
  206.         return(0);
  207.     switch(ckey) {
  208.     case bol_char:        bol_cmd();        break;
  209.     case eol_char:        eol_cmd();        break;
  210.     case NextWord_char:    skip_word(1);        break;
  211.     case PrevWord_char:    skip_word(0);        break;
  212.     case left_char:        left_cmd(1);        break;
  213.     case right_char:    right_cmd(1);        break;
  214.     case up_char:        up_cmd(1);        break;
  215.     case down_char:        down_cmd(1);        break;
  216.     case pageup_char:    pageup_cmd();        break;
  217.     case pagedown_char:    pagedown_cmd();        break;
  218.     case bs:        rubout_char();        break;
  219.     case Del_char:        kill_char();        break;
  220.     case bof_char:        bof_cmd();        break;
  221.     case eof_char:        eof_cmd();        break;
  222.     default :        found = false;        break;
  223.     }
  224.     lkey = ckey;
  225.     if (found) flush_kbd();
  226.     return(found);
  227. }
  228.  
  229. /*
  230.     Function to process Text window Alpha commands
  231. */
  232. TW_Cmds()
  233. {
  234.     int    found = true;
  235.  
  236.     if (!TWart_ptr && ckey != ATS)        /* if no article then    */
  237.         return(0);            /* can select it...    */
  238.     switch(ckey) {
  239.     case ATA:
  240.         Again_cmd();            /* from keyboard only    */
  241.         break;
  242.     case ATF: case ATR: case ATV:
  243.         if (FindReplace_cmd(1L,ckey == ATF ? 1:ckey == ATR ? 2:3))
  244.             last_again = ckey;
  245.         else    last_again = 0;
  246.         break;
  247.     case ATJ: case ATM:
  248.         JumpMrk_cmd(ckey == ATM);
  249.         break;
  250.     default :
  251.         if (mrkfctN)
  252.             found = false;
  253.         else
  254.         switch(ckey) {
  255.         case ATD:
  256.             Delete_cmd();    break;
  257.         case ATB:
  258.             Buffer_cmd();    break;
  259.         case ATT:
  260.         case ATL:
  261.             InsTag_cmd(ckey);break;
  262.         case Ins_char:
  263.             inIOm = !inIOm;        /* from keyboard only    */
  264.             TW_state();    break;
  265.         case ATS:
  266.             SelArt_cmd();    break;
  267.         case ATG:
  268.             Get_cmd();    break;
  269.         case ATC:
  270.             Copy_cmd();    break;
  271.         case ATX:
  272.             DelTag_cmd();    break;
  273.         case ATP:
  274.             PiTag_cmd(1);    break;
  275.         default :
  276.             found = false;    break;
  277.         }
  278.         break;
  279.     }
  280.     return(found);
  281. }
  282.  
  283. /*
  284.     Input routine when in Ins/Ovw mode or Block functions
  285.     Returns 0 for Abort or 1 for valid character.
  286. */
  287. Ikey()
  288. {
  289.     int    ret;            /* dummy variable    */
  290.     int    event;            /* which event returned    */
  291.     int    check;            /* check mark mode flag    */
  292.     unsigned kstat;            /* Kbd shift state    */
  293.     unsigned kcode;            /* Kbd return code    */
  294.  
  295.     if (check_TWtop()) while (1) {
  296.       wind_update(check = false);
  297.       event = evnt_multi(MU_MESAG | MU_KEYBD | MU_BUTTON,
  298.         1,1,1,
  299.         0,0,0,0,0,
  300.         0,0,0,0,0,
  301.         msg_buff,0,0,&ret,&ret,&ret,&kstat,&kcode,&ret);
  302.       wind_update(true);
  303.       if (event & MU_MESAG) {
  304.         if (msg_buff[0] == MN_SELECTED) {
  305.           if (msg_buff[3] == TEXT) {    /* check for TW menu    */
  306.             if (!TW_menu(msg_buff[4]) &&
  307.                  TWart_ptr && mrkfctN)
  308.                 check = true;
  309.  
  310.           }
  311.           else    menu_handler(msg_buff[3],msg_buff[4]);
  312.         }
  313.         else    mesag_handle(msg_buff);    /* else go to handler    */
  314.       }
  315.       if (!check_TWtop() && !TWart_ptr)
  316.         return(0);
  317.       if (event & MU_KEYBD) {
  318.         ckey = mapkbd(kstat,kcode);
  319.         if (!TW_Keys() && !TW_Cmds() && TWart_ptr) {
  320.             if (mrkfctN)
  321.                 check = true;
  322.             else
  323.             if (dscck())
  324.                 return(1);
  325.         }
  326.       }
  327.       if (event & MU_BUTTON)
  328.         check = TW_button();
  329.       if (check && (ret = mark_Key()))
  330.         return(ret - 1);
  331.     }
  332.     else    return(0);
  333. }
  334.  
  335. /*
  336.     Routine to scan for valid DeskSet character codes
  337. */
  338. dscck()
  339. {
  340.     return( (ckey >= 0x20 && ckey <= 0xbf)    ||
  341.         (ckey >= 0xf0 && ckey <= 0xfe)    ||
  342.         nocp(ckey) );
  343. }
  344.  
  345. /*
  346.     Routine to check for abort or close command in mark block mode
  347. */
  348. mark_Key()
  349. {
  350.     if (ckey == esc || ckey == ctl_C)
  351.         return(1);
  352.     else
  353.     if (ckey == mrkfbrk)
  354.         return(2);
  355.     else    return(0);
  356. }
  357.  
  358. /*
  359.     Function to move forward in the text buffer.
  360.     Returns updated pointer.
  361. */
  362. unsigned char *mvfwd(ptr)
  363. unsigned char *ptr;
  364. {
  365.     switch(*ptr) {
  366.     case hrt: case srt: case Rf:
  367.         ptr += 3;
  368.         break;
  369.     default:
  370.         ptr = skiptag(ptr);
  371.         if (*ptr != cr)
  372.             break;
  373.     case cr:
  374.         ptr += 2;
  375.         break;
  376.     }
  377.     return(ptr);
  378. }
  379.  
  380. /*
  381.     Function to move backward in the text buffer.
  382.     Returns updated pointer.
  383. */
  384. unsigned char *mvbwd(ptr)
  385. unsigned char *ptr;
  386. {
  387.     if (tagc(*(ptr-2)))
  388.         ptr -= 2;
  389.     else
  390.     if (*(--ptr) == lf) {
  391.         ptr -= 2;
  392.         if (tagc(*(ptr-1)))
  393.             --ptr;
  394.     }
  395.     return(ptr);
  396. }
  397.  
  398. /*
  399.     Function to delete from current char to tag
  400. */
  401. delete_chars(tag)
  402. int    tag;
  403. {
  404.     if (current_char > wdw_ptr[tag])        /* for first buffer  */
  405.         free_start    = wdw_ptr[tag];
  406.     else    current_char    = wdw_ptr[tag];
  407.     if (wdw_ptr[top_line] >= free_start &&        /* if deleting line1 */
  408.         wdw_ptr[top_line] < current_char)
  409.         setwptr(top_line);
  410.     TWrewindow(current_char);
  411.     nsline();
  412.     if (tag == HMRK)
  413.         ckTWsliderV();
  414.     TWaltered = true;
  415. }
  416.  
  417. /*
  418.     Function to check edit buffer limit. Returns true/false
  419. */
  420. Infsp()
  421. {
  422.     if (nofsp()) {
  423.         beep();
  424.         do_alert(BFERR1);
  425.         return(0);
  426.     }
  427.     return(1);
  428. }
  429.  
  430. /*
  431.     Function to change an alpha character to the other case.
  432.     Returns new or old character.
  433. */
  434. static    char unc(c)
  435. char    c;
  436. {
  437.     if (c >= 'a' && c <= 'z') c -= 0x20;
  438.     else
  439.     if (c >= 'A' && c <= 'Z') c += 0x20;
  440.     return(c);
  441. }
  442.  
  443. /*
  444.     Function to forward find a string.
  445.     Returns last search pointer.
  446. */
  447. unsigned char    *f_find(chr, target, count)
  448. unsigned char    chr, *target;
  449. unsigned long    count;
  450. {
  451.     unsigned char    cchr;
  452.     ++count;
  453.     cchr = setp.cign ? unc(chr):chr;
  454.     while (count-- && *target != chr && *target != cchr) ++target;
  455.     return(target);
  456. }
  457.  
  458. /*
  459.     Function to reverse find a string.
  460.     Returns last search pointer.
  461. */
  462. unsigned char    *r_find(chr, target, count)
  463. unsigned char    chr, *target;
  464. unsigned long    count;
  465. {
  466.     unsigned char    cchr;
  467.     ++count;
  468.     cchr = setp.cign ? unc(chr):chr;
  469.     while (count-- && *target != chr && *target != cchr) --target;
  470.     return(target);
  471. }
  472.  
  473. /*
  474.     Function to match a text string in search_stg to the data from ptr.
  475.     Direction denotes forward if true or backward if false.
  476. */
  477. match_string(ptr,direction)
  478. unsigned char    *ptr;
  479. int        direction;
  480. {
  481.     unsigned char    *target, *source;
  482.     int        len;
  483.  
  484.     if (direction) {
  485.       target = &search_stg[0];
  486.       source = ptr;
  487.       while (*target) {
  488.         if (setp.cign) {
  489.         if (toupper(*target) != toupper(*source)) break;
  490.         }
  491.         else if (*target != *source) break;
  492.         ++target; ++source;
  493.         if (source > buf_end) break;
  494.       }
  495.       if (!*target) {
  496.         last_one = source;
  497.         return(true);
  498.       }
  499.       else    return(false);
  500.     }
  501.     else {
  502.       if ((len = strlen(search_stg)) == 1) {
  503.         last_one = ptr;
  504.         return(true);
  505.       }
  506.       target = &search_stg[len-1];
  507.       source = ptr;
  508.       while (target >= search_stg) {
  509.         if (setp.cign) {
  510.         if (toupper(*target) != toupper(*source)) break;
  511.         }
  512.         else if (*target != *source) break;
  513.         --target; --source;
  514.         if (source < buf_start) break;
  515.       }
  516.       if (target == search_stg - 1) {
  517.         last_one = source + 1;
  518.         return(true);
  519.       }
  520.       else    return(false);
  521.     }
  522. }
  523.  
  524. /*
  525.     Function to perform a Cursor-Up command
  526. */
  527. up_cmd(count)
  528. int    count;
  529. {
  530.     if (free_start == buf_start)
  531.         return;
  532.     if (backup(count) == count)
  533.         movetoCcol();
  534.     nscr(0);
  535. }
  536.  
  537. /*
  538.     Function to perform a Cursor-Down command
  539. */
  540. down_cmd(count)
  541. int    count;
  542. {
  543.     if (current_char == buf_end)
  544.         return;
  545.     if (forup(count) == count)
  546.         movetoCcol();
  547.     nscr(0);
  548. }
  549.  
  550. /*
  551.     Function to perform a Cursor-Left command
  552. */
  553. left_cmd(count)
  554. int    count;
  555. {
  556.     unsigned char *ptr = free_start;
  557.     if (ptr == buf_start)
  558.         return;
  559.     while (count-- && ptr > buf_start)
  560.         ptr = mvbwd(ptr);
  561.     rwnscr(ptr,0);
  562. }
  563.  
  564. /*
  565.     Function to perform a Cursor-Right command
  566. */
  567. right_cmd(count)
  568. int    count;
  569. {
  570.     unsigned char *ptr = current_char;
  571.     if (ptr == buf_end)
  572.         return;
  573.     while (count-- && ptr < buf_end)
  574.         ptr = mvfwd(ptr);
  575.     rwnscr(ptr,0);
  576. }
  577.  
  578. /*
  579.     Function to perform a Beginning of Line command by Shift Left
  580. */
  581. bol_cmd()
  582. {
  583.     if (lkey == bol_char) {
  584.         ckey = 0;
  585.         if (wdw_ptr[top_line] == current_char)
  586.             return;
  587.         TWrewindow(wdw_ptr[top_line]);    /* to top of screen instead  */
  588.     }
  589.     else {
  590.         if (wdw_ptr[cur_line()] == current_char)
  591.             return;
  592.         backup(0);            /* beginning of current line */
  593.     }
  594.     nscr(0);
  595. }
  596.  
  597. /*
  598.     Function to perform a End of Line command by Shift Right
  599. */
  600. eol_cmd()
  601. {
  602.     if (lkey == eol_char) {
  603.         ckey = 0;
  604.         if (current.row == current.mrow - 1)
  605.             return;
  606.         TWrewindow(wdw_ptr[bot_line()]);    /* to the last line  */
  607.     }
  608.     else {
  609.         if (lpend(current_char))
  610.             return;
  611.         forup(0);            /* to end of current line    */
  612.     }
  613.     nscr(0);
  614. }
  615.  
  616. /*
  617.     Function to perform a Page-Up command by Shift Up
  618. */
  619. pageup_cmd()
  620. {
  621.     if (current_char == buf_start)
  622.         return;
  623.     TWrewindow(wdw_ptr[top_line]);
  624.     backup(current.mrow - 3);
  625.     nscr(1);
  626. }
  627.  
  628. /*
  629.     Function to perform a Page-Down command by Shift Down
  630. */
  631. pagedown_cmd()
  632. {
  633.     if (current_char == buf_end)
  634.         return;
  635.     TWrewindow(wdw_ptr[bot_line()]);
  636.     forup(3);
  637.     nscr(1);
  638. }
  639.  
  640. /*
  641.     Function to perform a Beginning of File command by Ctl Up
  642. */
  643. bof_cmd()
  644. {
  645.     if (current_char == buf_start)
  646.         return;
  647.     rwnscr(buf_start,1);
  648. }
  649.  
  650. /*
  651.     Function to perform an End of File command by Ctl Down
  652. */
  653. eof_cmd()
  654. {
  655.     if (current_char == buf_end)
  656.         return;
  657.     rwnscr(buf_end,1);
  658. }
  659.  
  660. /*
  661.     Function to find forward or backward the next word
  662.     by Ctl Right or Left
  663. */
  664. skip_word(direction)
  665. int    direction;
  666. {
  667.     unsigned char    *ptr;
  668.     
  669.     if (direction) {            /* either forwards    */
  670.         if (current_char == buf_end)
  671.             return;
  672.         ptr = current_char;
  673.         while ( ptr < buf_end &&    /* skip current word    */
  674.             (calpha(*ptr) || cdigit(*ptr)) )
  675.             ++ptr;
  676.         while ( ptr < buf_end &&    /* skip to next word    */
  677.             !calpha(*ptr) && !cdigit(*ptr) )
  678.             ptr = skiptag(ptr);
  679.     }
  680.     else {                    /* or backwards        */
  681.         if (free_start == buf_start)
  682.             return;
  683.         ptr = free_start;
  684.         while ( ptr > buf_start &&    /* skip current word    */
  685.             !tagc(*(ptr-2)) &&
  686.             (calpha(*(ptr-1)) || cdigit(*(ptr-1))) )
  687.             --ptr;
  688.         while ( ptr > buf_start ) {    /* scan for prev word    */
  689.             if (tagc(*(ptr-2)))
  690.                 ptr -= 2;
  691.             else
  692.             if (!calpha(*(ptr-1)) && !cdigit(*(ptr-1)))
  693.                 --ptr;
  694.             else    break;
  695.         }
  696.         if (ptr > buf_start) --ptr;    /* set to end of word    */
  697.     }
  698.     rwnscr(ptr,0);
  699. }
  700.  
  701. /*
  702.     Function to delete a character at cursor
  703. */
  704. kill_char()
  705. {
  706.     int        nline;
  707.     unsigned char    *ptr = current_char;
  708.     if (ptr < buf_end) {
  709.         if (ctagc(*ptr))
  710.             return(right_cmd(1));
  711.         else
  712.         if (nline = allend(*ptr))
  713.             ptr += 3;
  714.         else
  715.         if (ptagc(*ptr) ||
  716.            (nline = (*(++ptr) == cr)))
  717.             ptr += 2;
  718.         if (ptr <= buf_end) {
  719.             wdw_ptr[TMP1] = ptr;
  720.             delete_chars(TMP1);
  721.             if (nline) ckTWsliderV();
  722.         }
  723.     }
  724. }
  725.  
  726. /*
  727.     Function to delete a character prior to the cursor
  728. */
  729. rubout_char()
  730. {
  731.     int        nline = 0;
  732.     unsigned char    *ptr = free_start;
  733.     if (ptr > buf_start) {
  734.         if (ctagc(*(ptr-2)))
  735.             return(left_cmd(1));
  736.         else
  737.         if (ptagc(*(ptr-2)))
  738.             ptr -= 2;
  739.         else
  740.         if (nline = (*(--ptr) == lf)) {
  741.             ptr -= 2;
  742.             if (tagc(*(ptr-1)))
  743.                 ++ptr;
  744.         }
  745.         if (ptr >= buf_start) {
  746.             setwptr(TMP1);
  747.             TWrewindow(ptr);
  748.             delete_chars(TMP1);
  749.             if (nline) ckTWsliderV();
  750.         }
  751.     }
  752. }
  753.  
  754. /*
  755.     Command to perform global search (forward or backward)
  756.     then optionally replace with user string after match.
  757.     Can be repeated by user specified number of times.
  758. */
  759. FindReplace_cmd(repeat,direction)
  760. unsigned long    repeat;
  761. int        direction;
  762. {
  763.     OBJECT        *dialog;
  764.     int        bxobj, stobj, exobj, abobj, ulobj;
  765.     int        i, status, mod, slen, rlen;
  766.     unsigned long    begcnt;
  767.     unsigned char    *ptr;
  768.  
  769.     mod = abs(direction);
  770.     if (direction < 0) goto FR_ag;            /* detect Again mode */
  771.     if (mod == 1)                    /* for 1, Find         */
  772.       bxobj = FIND, stobj = FFST,
  773.       ulobj = FDUL, abobj = FDNOK;
  774.     else
  775.     if (mod == 2)                    /* for 2, Replace    */
  776.       bxobj = RPLACE, stobj = RFST,
  777.       ulobj = RPUL,   abobj = RPNOK;
  778.     else                        /* for 3, Rev. find  */
  779.       bxobj = RFIND, stobj = RVST,
  780.       ulobj = RVFUL, abobj = RVFNOK;
  781.  
  782.     rsrc_gaddr(0,bxobj,&dialog);
  783.     dialog[ulobj].ob_state = setp.cign ? SELECTED:NORMAL;
  784.     set_tedit(dialog,stobj,search_stg);
  785.     if (mod == 2)                    /* for Replace only  */
  786.         set_tedit(dialog,RRST,replace_stg);
  787.  
  788.     exobj = execform(dialog,0);
  789.     dialog[exobj].ob_state = NORMAL;
  790.     if (exobj == abobj)
  791.         return(false);
  792.     BWredraw();                    /* redraw T/P Window */
  793.     setp.cign = (dialog[ulobj].ob_state == SELECTED);
  794.     strcpy(search_stg,get_edit(dialog,stobj));
  795.     if (mod == 2) {                    /* for Replace only  */
  796.         strcpy(replace_stg,get_edit(dialog,RRST));
  797.         if (exobj == RPALL)
  798.             repeat = -1L;
  799.     }
  800.  
  801. FR_ag:    if (!*search_stg)
  802.         return(false);                /* nothing to find   */
  803.     slen = strlen(search_stg);            /* use search length */
  804.     last_one = current_char;
  805.     ptr = mod < 3 ? current_char:free_start-1;
  806.     status = true;
  807.     begcnt = repeat - 1;
  808.  
  809.     while (repeat--) {
  810.       if (mod < 3) while (1) {            /* forward search... */
  811.         if ( ptr >= buf_end ||
  812.         (ptr = f_find(search_stg[0],ptr,(long)(buf_end - ptr) + 1))
  813.             >= buf_end ) {
  814. FR_nf:        if (repeat == begcnt)
  815.             do_alert(FRNFD);
  816.         status = false;
  817.         goto FR_ex;
  818.         }
  819.         else if (match_string(ptr,1)) {
  820.         if (mod == 1) {            /* for fwd search only done  */
  821.             if (repeat) ++ptr; break;
  822.         }                /* else do string replace... */
  823.         TWrewindow(ptr);        /* string is at current char */
  824.         rlen = strlen(replace_stg);
  825.         if (free_start + rlen >= current_char + slen - MIN_LEFT) {
  826.             do_alert(FRBFE);
  827.             status = false;
  828.             goto FR_ex;
  829.         }
  830.         i = cur_line();
  831.         if (wdw_ptr[i] == current_char)
  832.             wdw_ptr[i] = free_start;
  833.         current_char += slen;            /* delete old one... */
  834.         strcpy(free_start,replace_stg);
  835.         free_start += rlen;            /* & insert new one. */
  836.         ptr = current_char;
  837.         TWaltered = true;            /* mark text altered */
  838.         break;
  839.         }
  840.         else ++ptr;
  841.       }
  842.       else while (1) {                /* reverse search... */
  843.         if (ptr <= buf_start ||
  844.         (ptr = r_find(search_stg[slen-1],ptr,(long)(ptr - buf_start)))
  845.             <= buf_start )
  846.             goto FR_nf;
  847.         else if (match_string(ptr,0)) {
  848.         if (repeat) --ptr; break;
  849.         }
  850.         else --ptr;
  851.       }
  852.     }
  853. FR_ex:    TWrewindow(last_one);
  854.     if (mod == 1 || mod == 3)        /* for Forward/Reverse Find  */
  855.         Creview(0);
  856.     else {                    /* else for Replace only...  */
  857.         for (i = bot_line();i > top_line;--i)
  858.             if (wdw_ptr[i]) break;        /* ensure new screen */
  859.         Creview(last_one < wdw_ptr[i] ? 3:2);
  860.     }
  861.     cursor();
  862.     return(status);
  863. }
  864.  
  865. /*
  866.     Function to repeat the last Search/Replace command
  867. */
  868. Again_cmd()
  869. {
  870.     int    mod;
  871.  
  872.     if (!last_again)
  873.         return;
  874.     if (last_again == ATF) mod = -1;
  875.     else
  876.     if (last_again == ATR) mod = -2;
  877.     else
  878.     if (last_again == ATV) mod = -3;
  879.     if (!FindReplace_cmd(1L,mod))
  880.         last_again = 0;
  881. }
  882.  
  883. /*
  884.     Function to set either Insert/Overwrite mode state
  885.     or current Mark command on Info line.
  886. */
  887. TW_state()
  888. {
  889.     int    msgno;
  890.  
  891.     if (mrkfctN)
  892.         msgno = mrkfctN;
  893.     else
  894.     if (inIOm) {
  895.         msgno = INMS;    wdw_crsnm();
  896.     }
  897.     else {
  898.         msgno = OVMS;    wdw_crsbx();
  899.     }
  900.     TW_info(msgno);
  901. }
  902.  
  903. /*
  904.     Editor handler
  905. */
  906. Editor()
  907. {
  908.     while (1) {
  909.       if (!Ikey())                    /* time to quit mode */
  910.         return;
  911.       else {                    /* or stay in mode.. */
  912.         if ((ckey == ' '        &&        /* check 2 spaces    */
  913.         getLch(free_start-1) == ' ')
  914.             ||
  915.         (ckey != ' '        &&        /* check flash pos.  */
  916.         !nocp(ckey)        &&
  917.         getfp(ckey) == 0xff)) {
  918.         beep(); continue;            /* error skip input  */
  919.         }
  920.         if (!Infsp()) continue;            /* no room continue  */
  921.         if (ckey == cr) ckey = hrt;            /* swap cr to hrt... */
  922.         if (allend(ckey)) {                /* user line endings */
  923.         TWclipdraw(wdw_eol,ckey);        /* update wdow line  */
  924.         *free_start++ = ckey;            /* insert hrt/cr/lf  */
  925.         ckcrlf();
  926.         if (wdw_ptr[cur_line()] == current_char)
  927.             wdw_ptr[cur_line()] = free_start - 3;
  928.         nsline();
  929.         }
  930.         else {                    /* or user reg input */
  931.         if (    inIOm            ||    /* if in Insert mode */
  932.             tagc(*current_char)    ||    /* or cursor at TAG  */
  933.             allend(*current_char)    ||    /* or at line ending */
  934.             current_char >= buf_end ) {    /* or at end buffer  */
  935.             *(--current_char) = ckey;    /* do Insert mode... */
  936.             if (!TWhclip && !current.col)
  937.                 setwptr(cur_line());
  938.         }
  939.         else    *current_char = ckey;        /* else do Overwrite */
  940.         wdw_ptr[HMRK] = skiptag(current_char);
  941.         if (*wdw_ptr[HMRK] == cr)
  942.             wdw_ptr[HMRK] += 2;
  943.         cursor();
  944.         TWclipdraw(rewrite_line,0);        /* now refresh line  */
  945.         TWrewindow(wdw_ptr[HMRK]);
  946.         cursor();
  947.         }
  948.         TWaltered = true;                /* set file altered  */
  949.       }                        /* end of stayinmode */
  950.     }                        /* end of while (1)  */
  951. }
  952.  
  953. /*
  954.     Command to jump and set cursor to an user specified marker.
  955. */
  956. JumpMrk_cmd(which)
  957. int    which;
  958. {
  959.     OBJECT    *dialog;
  960.     int    bxobj, exobj, abobj, bn;
  961.  
  962.     if (which)                /* for Set Marker cmd    */
  963.       bxobj = SETAG, abobj = STGNOK;
  964.     else                    /* for Jump Marker cmd    */
  965.       bxobj = JPTAG, abobj = JTGNOK;
  966.     rsrc_gaddr(0,bxobj,&dialog);
  967.     exobj = execform(dialog,0);
  968.     dialog[exobj].ob_state = NORMAL;
  969.     if (exobj == abobj)
  970.         return;
  971.     BWredraw();                /* redraw T/P Windows    */
  972.     switch(exobj) {
  973.     case STGA:/* case JTGA: same */
  974.         bn = mrk_base;
  975.         break;
  976.     case STGB:/* case JTGB: same */
  977.         bn = mrk_base + 1;
  978.         break;
  979.     case STGC:/* case JTGC: same */
  980.         bn = mrk_base + 2;
  981.         break;
  982.     case STGD:/* case JTGD: same */
  983.         bn = mrk_base + 3;
  984.         break;
  985.     }
  986.     if (which)
  987.         setwptr(bn);
  988.     else
  989.     if (current_char != wdw_ptr[bn]) {
  990.         TWrewindow(wdw_ptr[bn]);
  991.         nscr(0);
  992.     }
  993. }
  994.  
  995. /*
  996.     Routine to (un)check a mark function in Text menu
  997.     and (en)disable inappropriate functions in mark mode.
  998. */
  999. mrkfcheck(mode)
  1000. int    mode;
  1001. {
  1002.     int    markf, disf1, disf2, disf3;
  1003.  
  1004.     switch(mrkfbrk) {
  1005.     case ATD:    markf = DELTXT;
  1006.             disf1 = BUFTXT;
  1007.             disf2 = INSTAG;
  1008.             disf3 = INSLTAG;
  1009.             break;
  1010.     case ATB:    markf = BUFTXT;
  1011.             disf1 = DELTXT;
  1012.             disf2 = INSTAG;
  1013.             disf3 = INSLTAG;
  1014.             break;
  1015.     case ATT:    markf = INSTAG;
  1016.             disf1 = DELTXT;
  1017.             disf2 = BUFTXT;
  1018.             disf3 = INSLTAG;
  1019.             break;
  1020.     case ATL:    markf = INSLTAG;
  1021.             disf1 = DELTXT;
  1022.             disf2 = BUFTXT;
  1023.             disf3 = INSTAG;
  1024.             break;
  1025.     }
  1026.     menu_icheck (ad_menu,markf,mode);
  1027.     menu_ienable(ad_menu,disf1,!mode);
  1028.     menu_ienable(ad_menu,disf2,!mode);
  1029.     menu_ienable(ad_menu,disf3,!mode);
  1030.     menu_ienable(ad_menu,SELART,!mode);
  1031.     menu_ienable(ad_menu,GETXT,!mode);
  1032.     menu_ienable(ad_menu,CPYTXT,!mode);
  1033.     menu_ienable(ad_menu,DELTAG,!mode);
  1034. }
  1035.  
  1036. /*
  1037.     Function to mark a block
  1038. */
  1039. mark_blk(fctN,fbrk)
  1040. int    fctN;
  1041. char    fbrk;
  1042. {
  1043.     mrkfctN = fctN;
  1044.     mrkfbrk = fbrk;
  1045.     mrkfcheck(true);
  1046.     TW_state();
  1047.     cursor();
  1048.     setwptr(HMRK);
  1049.     wdw_mark();
  1050.     fctN = Ikey();
  1051.     mrkfcheck(false);
  1052.     mrkfctN = false;
  1053.     return(fctN);
  1054. }
  1055.  
  1056. /*
  1057.     Function to find matching start or end Tag
  1058. */
  1059. unsigned char    *match_tag(fdir,tagn,sptr,eptr)
  1060. int        fdir;
  1061. unsigned char    tagn, *sptr, *eptr;
  1062. {
  1063.     if (fdir) {                /* test find ETAG    */
  1064.       if (sptr >= eptr)
  1065.         goto quit;
  1066.       while (sptr < eptr) {            /* scan forward...    */
  1067.         if (*sptr == ETAG && *(sptr+1) == tagn)
  1068.             return(sptr);
  1069.         sptr = mvfwd(sptr);
  1070.       }
  1071.     }
  1072.     else {                    /* or    find STAG    */
  1073.       if (sptr == eptr)
  1074.         goto quit;
  1075.       while (sptr > eptr) {            /* scan backward...    */
  1076.         sptr = mvbwd(sptr);
  1077.         if (*sptr == STAG && *(sptr+1) == tagn)
  1078.             return(sptr);
  1079.       }
  1080.     }
  1081. quit:    return((char *)0);            /* search fails...    */
  1082. }
  1083.  
  1084. /*
  1085.     Function to check for unmatched start and end Tag
  1086.     within a block delimited by HMRK(start) and TMP1(end)
  1087. */
  1088. UnmatchTag()
  1089. {
  1090.     unsigned char    *sp, *ep;
  1091.     int        err = 0;
  1092.  
  1093.     if (wdw_ptr[HMRK] > current_char)    /* if start tag    ptr    */
  1094.     {                    /* in 2nd partition    */
  1095.         wdw_ptr[TMP1] = wdw_ptr[HMRK];
  1096.         setwptr(HMRK);            /* swap begin/end ptr    */
  1097.     }
  1098.     else    setwptr(TMP1);            /* else set end tag ptr    */
  1099.     TWrewindow(wdw_ptr[HMRK]);        /* to begin tag mark to    */
  1100.     for (    sp = current_char,        /* check unclosed STAG    */
  1101.         ep = wdw_ptr[TMP1];
  1102.         !err && sp < ep;
  1103.         sp = mvfwd(sp)    )
  1104.       if (*sp == STAG &&                /* if hit STAG    */
  1105.         !match_tag(1,*(sp+1),sp+2,ep))        /* find   ETAG    */
  1106.       {    do_alert(TAGERR2);        /* no match error quit    */
  1107.         err = 1;    }
  1108.     TWrewindow(wdw_ptr[TMP1]);        /* to end tag mark to    */
  1109.     if (!err)
  1110.     for (    sp = free_start,        /* check unclosed ETAG    */
  1111.         ep = wdw_ptr[HMRK];
  1112.         !err && sp > ep;  ) {
  1113.       sp = mvbwd(sp);
  1114.       if (*sp == ETAG &&                /* if hit ETAG    */
  1115.         !match_tag(0,*(sp+1),sp,ep))        /* find   STAG    */
  1116.       {    do_alert(TAGERR2);        /* no match error quit    */
  1117.         err = 1;    }
  1118.     }
  1119.     return(err);
  1120. }
  1121.  
  1122. /*
  1123.     Command to perform block deletion from cursor
  1124. */
  1125. Delete_cmd()
  1126. {
  1127.     int    no_fit;
  1128.     
  1129.     if (!mark_blk(DMENU,ATD)) {
  1130.         if (!check_TWtop())
  1131.             return;
  1132.         else    goto del_q;
  1133.     }
  1134.     if (!wdw_ptr[HMRK] || wdw_ptr[HMRK] == current_char)
  1135.         goto del_q;
  1136.     if (wdw_ptr[HMRK] < current_char) {    /* in 1st partition    */
  1137. /*?*/        if (*current_char == cr)
  1138.             TWrewindow(current_char + 2);
  1139.         else
  1140.         if (*current_char == srt)
  1141.             TWrewindow(current_char + 3);
  1142.     }
  1143.     else
  1144.     if (wdw_ptr[HMRK] > current_char) {    /* in 2nd partition    */
  1145. /*?*/        if (*wdw_ptr[HMRK] == cr)
  1146.             wdw_ptr[HMRK] += 2;
  1147.         else
  1148.         if (*wdw_ptr[HMRK] == srt)
  1149.             wdw_ptr[HMRK] += 3;
  1150.     }
  1151.     if (UnmatchTag())            /* check unmatched tag    */
  1152.         goto del_q;
  1153.     no_fit = cb_bufin(wdw_ptr[HMRK],(long)(free_start - wdw_ptr[HMRK]));
  1154.     if (no_fit) {        /* if deleted data cannot be saved...    */
  1155.         if (do_alert(DELOK) == 2)    /* check with user...    */
  1156. del_q:            nscr(3);
  1157.         else    delete_chars(HMRK);    /* ok..do the deletion    */
  1158.     }
  1159.     else    delete_chars(HMRK);        /* else do the deletion    */
  1160.     TW_state();
  1161. }
  1162.  
  1163. /*
  1164.     Command to perform data buffering by saving it into the copy
  1165.     buffer for later use... like block move...
  1166. */
  1167. Buffer_cmd()
  1168. {
  1169.     if (!mark_blk(BMENU,ATB)) {
  1170.         if (!check_TWtop())
  1171.             return;
  1172.         else    goto buf_q;
  1173.     }
  1174.     if (!wdw_ptr[HMRK] || wdw_ptr[HMRK] == current_char)
  1175.         goto buf_q;
  1176.     if (UnmatchTag())            /* check unmatched tag    */
  1177.         goto buf_q;
  1178.     if (cb_bufin(wdw_ptr[HMRK],(long)(free_start - wdw_ptr[HMRK])))
  1179.         do_alert(TBMS);
  1180. buf_q:    nscr(3);
  1181.     TW_state();
  1182. }
  1183.     
  1184. /*
  1185.     Command to perform Tag insertion
  1186.     mode :    ATT -- Global
  1187.         ATL -- Local
  1188. */
  1189. InsTag_cmd(mode)
  1190. unsigned char    mode;
  1191. {
  1192.     unsigned    tagnum, Local;
  1193.  
  1194.     Ins_Tag = true;
  1195.     Local    = (mode == ATL);
  1196.     if (!mark_blk(Local ? ILTAG:IGTAG,mode)) {
  1197.         if (!check_TWtop())
  1198.             return(Ins_Tag = false);
  1199.         else    goto inT_q;
  1200.     }
  1201.     if (!wdw_ptr[HMRK] || wdw_ptr[HMRK] == current_char)
  1202.         goto inT_q;
  1203.     if (Infsp() && !UnmatchTag()) {        /* check insert space    */
  1204.                         /* and unmatched tag    */
  1205.         if (Local)            /* if Local Tag mode    */
  1206.             tagnum = last_tag;    /* use last tag number    */
  1207.         else    tagnum = 1;
  1208.         tagnum = do_tag(tagnum,1);    /* call Tag dialog box    */
  1209.         BWredraw();            /* redraw T/P Windows    */
  1210.         if (tagnum) {            /* valid tag selected ?    */
  1211.           if (Local) {            /* if Local Tag mode    */
  1212.             if (last_tag == tagnum &&
  1213.               ++last_tag > NUMTAG)
  1214.                 last_tag = BLTAG;
  1215. /*            last_tag = tagnum;    ** update last tag #    */
  1216.           }
  1217.           --tagnum;            /* tag start from 0    */
  1218.           TWrewindow(wdw_ptr[HMRK]);    /* to begin tag mark    */
  1219.           if (wdw_ptr[cur_line()] == current_char)
  1220.             wdw_ptr[cur_line()] = free_start;
  1221.           *free_start++ = STAG;        /* insert STAG+tagnum    */
  1222.           *free_start++ = (char)tagnum;
  1223.           TWrewindow(wdw_ptr[TMP1]);    /* to end tag mark    */
  1224.           *free_start++ = ETAG;        /* insert ETAG+tagnum    */
  1225.           *free_start++ = (char)tagnum;
  1226.           TWrewindow(current_char);
  1227.           TWaltered = true;
  1228.         }
  1229.     }
  1230. inT_q:    nscr(3);
  1231.     Ins_Tag = false;
  1232.     TW_state();
  1233. }
  1234.  
  1235. /*
  1236.     Command to perform Tag deletion
  1237. */
  1238. DelTag_cmd()
  1239. {
  1240.     int        fdir;            /* 1: fwd, 0: bwd mode    */
  1241.     unsigned char    *sp, *ep, tagn;
  1242.  
  1243.     if (!ctagc(*current_char))        /* if no TAG do exit...    */
  1244.         return;
  1245.     tagn    = *(current_char + 1);
  1246.     fdir    = (*current_char == STAG);    /* check search mode    */
  1247.     if (fdir) {                /* HMRK:start, TMP1:end    */
  1248.         setwptr(HMRK);            /* set HMRK find TMP1    */
  1249.         sp = current_char + 2;
  1250.         ep = buf_end;
  1251.     }
  1252.     else {
  1253.         setwptr(TMP1);            /* set TMP1 find HMRK    */
  1254.         sp = free_start;
  1255.         ep = buf_start;
  1256.     }
  1257.     if (!(ep = match_tag(fdir,tagn,sp,ep)))    /* find S or E TAG    */
  1258.         return(do_alert(TAGERR1));    /* no match error quit    */
  1259.     if (do_alert(KILLTAG) == 2)        /* recheck with user...    */
  1260.         return;                /* (s)he aborts, quit..    */
  1261.     wdw_ptr[fdir ? TMP1:HMRK] = ep;        /* save S or E    tag ptr    */
  1262.     wdw_ptr[TMP4] = current_char + 2;    /* save after    tag ptr    */
  1263.     TWrewindow(wdw_ptr[HMRK]);        /* to begin tag mark    */
  1264.     current_char += 2;
  1265.     TWrewindow(wdw_ptr[TMP1]);        /* to end   tag mark    */
  1266.     current_char += 2;
  1267.     TWrewindow(wdw_ptr[TMP4]);        /* to after tag mark    */
  1268.     nscr(3);
  1269.     TWaltered = true;
  1270. }
  1271.  
  1272. /*
  1273.     Command to perform data (created by the Delete or Buffer command)
  1274.     copy by restoring it from the copy buffer and inserting it at
  1275.     present cursor position.
  1276. */
  1277. Copy_cmd()
  1278. {
  1279.     unsigned char    *optr;
  1280.     unsigned long    fsp;
  1281.     
  1282.     if (!cb_size) return;
  1283.     TW_info(CMENU);
  1284.     fsp = free_space();
  1285.     if (fsp <= MIN_FREE || (unsigned long)cb_size > fsp - MIN_LEFT)
  1286.         do_alert(CPBFE);
  1287.     else {
  1288.         cb_bufout(optr = free_start);
  1289.         free_start += cb_size;
  1290.         TWrewindow(optr);
  1291.         nsline();
  1292.         ckTWsliderV();
  1293.         TWaltered = true;
  1294.     }
  1295.     TW_state();
  1296. }
  1297.  
  1298. /*
  1299.     Command to read in another file into the present edited article
  1300. */
  1301. Get_cmd()
  1302. {
  1303.     char    fname[100];
  1304.  
  1305.     TW_info(GMENU);
  1306.     if (gdosfname(fname,4,1)) {
  1307.         switch(read_file(fname)) {
  1308.         case -1:
  1309.             setnfd(fname,2);
  1310.             break;
  1311.         case 2:
  1312.             do_alert(BFERR2);
  1313.             break;
  1314.         case 1:
  1315.             do_alert(BFERR3);
  1316.         case 0:
  1317.             TWaltered = true;    /* set file altered  */
  1318.             break;
  1319.         }
  1320.         nsline();
  1321.         ckTWsliderV();
  1322.     }
  1323.     TW_state();
  1324. }
  1325.  
  1326. /*
  1327.     Command to select article from dialog box
  1328. */
  1329. extern    ARTICLE    *do_artobj();
  1330. SelArt_cmd()
  1331. {
  1332.     ARTICLE    *art_ptr;
  1333.  
  1334.     if (!(art_ptr = do_artobj()))        /* to selection dialog box  */
  1335.         return;
  1336.     if (TWart_ptr) saveTWptrs();        /* update old article ptrs  */
  1337.     TWart_ptr = art_ptr;
  1338.     setTWArt();                /* set current TW article   */
  1339.     TWrewindow(buf_start);            /* to beginning of article  */
  1340.     TWslider_chk();                /* reset TW H/Vsliders      */
  1341. }
  1342.  
  1343. /*
  1344.     Function to set article from region pointer
  1345. */
  1346. setTWArticle(rptr,txtptr)
  1347. REGION    *rptr;
  1348. char    *txtptr;
  1349. {
  1350.     TWart_ptr = rptr->artptr;        /* get article from region  */
  1351.     if (!TWart_ptr)                /* if no article associated */
  1352.         return(TW_name(nuls));        /* with region return...    */
  1353.     setTWArt();                /* set current TW article   */
  1354.     if (!txtptr)
  1355.         TWrewindow(rptr->txtstart);    /* to beginning of region   */
  1356.     else    TWrewindow(txtptr);
  1357.     TWslider_chk();                /* reset TW H/Vsliders      */
  1358. }
  1359.  
  1360. /*
  1361.     Function to set article from current TW article pointer
  1362. */
  1363. setTWArt()
  1364. {
  1365.     REGION    *rptr, *tptr;
  1366.     char    **bptr;
  1367.     int    i;
  1368.  
  1369.     get_abuffvars(TWart_ptr);        /* get article buffer ptrs  */
  1370.     rptr = TWart_ptr->regptr;        /* get first region        */
  1371.     if (rptr && (rptr = rptr->alink)) {
  1372.         upd_tags = 1;
  1373.         tptr = rptr;
  1374.         while (tptr = tptr->alink)
  1375.             ++upd_tags;
  1376.         if (upd_ptr = (char **)malloc(4 * upd_tags)) {
  1377.             bptr = upd_ptr;
  1378.             do *(bptr++) = rptr->txtstart;
  1379.             while (rptr = rptr->alink);
  1380.         }
  1381.     }
  1382.     for (i = 0;i < 4;) setwptr(i++);    /* reset all text markers   */
  1383.     TWaltered = 0;                /* reset buffer dirty flag  */
  1384.     TW_name(TWart_ptr->filename);        /* set TWname to art. name  */
  1385.     inIOm = 1;                /* start in Insert mode     */
  1386.     TW_state();
  1387. }
  1388.  
  1389. saveTWptrs()
  1390. {
  1391.     ARTICLE    *art_ptr;
  1392.     REGION    *rptr;
  1393.     char    **bptr;
  1394.  
  1395.     TWrewindow(buf_end);            /* to end of article    */
  1396.     put_abuffvars(art_ptr = TWart_ptr);    /* save art. buf. ptrs    */
  1397.     TWart_ptr = (ARTICLE *)0;        /* null TW article ptr    */
  1398.     TW_name(nuls);                /* clear window name    */
  1399.     TW_info(-1);
  1400.     if (TWaltered) {
  1401.         art_ptr->dirty = 1;        /* Set modified flag    */
  1402.         if (rptr = art_ptr->regptr) {
  1403.           if ((rptr = rptr->alink) && upd_ptr) {
  1404.             bptr = upd_ptr;
  1405.             do rptr->txtstart = *(bptr++);
  1406.             while (rptr = rptr->alink);
  1407.           }
  1408.           gl_region_ptr = art_ptr->regptr;
  1409.           recalc_rtext();
  1410.           force_draw_flag = 1;        /* Force redraw on Prev    */
  1411.         }
  1412.     }
  1413.     if (upd_ptr) {
  1414.         free(upd_ptr);
  1415.         upd_ptr = (char **)0;
  1416.     }
  1417. }
  1418.  
  1419. TWslider_chk()
  1420. {
  1421.     TWsliderH();                /* set Hslider position    */
  1422.     wind_set(txt_handle,WF_HSLSIZE,        /* set Hslider size    */
  1423.         scaler(1000,current.mcol,wdw_cols),0,0,0);
  1424.     TWsliderV();                /* set Vslider position    */
  1425. }
  1426.  
  1427. TWsliderV()
  1428. {
  1429.     if (TWart_ptr) currentVpos();
  1430.                         /* set Vslider position    */
  1431.     wind_set(txt_handle,WF_VSLIDE,TWVSLpos,0,0,0);
  1432.                         /* set Vslider size    */
  1433.     wind_set(txt_handle,WF_VSLSIZE,TWVSLsize,0,0,0);
  1434. }
  1435.  
  1436. TWsliderH()
  1437. {
  1438.     wind_set(txt_handle,WF_HSLIDE,
  1439.         scaler(1000,TWhclip,wdw_cols - current.mcol),0,0,0); 
  1440. }
  1441.  
  1442. TWvslide(position)
  1443. int    position;
  1444. {
  1445.     char    *txtptr;
  1446.     long    fsize;
  1447.  
  1448.     if (!TWart_ptr || position == TWVSLpos)
  1449.         return;
  1450.     if (position <= 1)
  1451.         bof_cmd();
  1452.     else
  1453.     if ((position + TWVSLsize) >= 1000)
  1454.         eof_cmd();
  1455.     else {
  1456.         fsize    = (long)(free_start - buf_start) +
  1457.               (long)(buf_end - current_char);
  1458.         txtptr    = buf_start + (((long)position * fsize) / 1000L);
  1459.         if (txtptr < free_start) {    /* if in 1st partition    */
  1460.           txtptr = prvp1(txtptr);
  1461.           if (*txtptr == cr)
  1462.             txtptr += 2;
  1463.         }
  1464.         if (txtptr >= free_start) {    /* if in 2nd partition    */
  1465.           txtptr = current_char + (long)(txtptr - free_start);
  1466.           if (txtptr == current_char)
  1467.             return;
  1468.           txtptr = prvp2(txtptr);
  1469.           if (*txtptr == cr)
  1470.             txtptr += 2;
  1471.           if (txtptr > buf_end)
  1472.             txtptr = buf_end;
  1473.         }
  1474.         TWrewindow(txtptr);
  1475.         backup(0);            /* to beginning of line    */
  1476.         nscr(1);
  1477.     }
  1478. }
  1479.  
  1480. TWhslide(position)
  1481. int    position;
  1482. {
  1483.     int    xdiff;
  1484.     int    curspos;
  1485.  
  1486.     if (!TWart_ptr)
  1487.         return;
  1488.     position = scaler(position,wdw_cols - current.mcol,1000);
  1489.     if (abs(TWhclip - position)) {
  1490.       curspos = TWhclip + current.col;
  1491.       xdiff      = abs(curspos - position);
  1492.       if (TWhclip > position)
  1493.         left_cmd(xdiff);
  1494.       else {
  1495.         if (position <= curspos)
  1496.             TWsetHclip(position);
  1497.         else    TWmoveRight(position,xdiff);
  1498.       }
  1499.     }
  1500. }
  1501.  
  1502. TWsetHclip(position)
  1503. int    position;
  1504. {
  1505.     TWhclip = position;
  1506.     TWsliderH();
  1507.     nscr(3);
  1508. }
  1509.  
  1510. TWmoveRight(position,moveR)
  1511. int    position, moveR;
  1512. {
  1513.     int    xdiff;
  1514.  
  1515.     if ((TWhclip + current.mcol) >= wdw_cols)
  1516.         return;
  1517.     xdiff = nchartoEline();            /* # of chars to eoline */
  1518.     if (xdiff > 0)                /* move cursor first    */
  1519.         right_cmd(xdiff > moveR ? moveR:xdiff);
  1520.     if (position != TWhclip) {        /* if hclip not correct    */
  1521.       if (position > (wdw_cols - current.mcol))
  1522.         position = wdw_cols - current.mcol;
  1523.       if (position > (TWhclip + current.col))
  1524.         position = TWhclip + current.col;
  1525.       TWsetHclip(position);            /* force rescreen...    */
  1526.     }
  1527. }
  1528.  
  1529. currentVpos()
  1530. {
  1531.     long    fsize, temp;
  1532.  
  1533.     temp    = (long)(free_start - buf_start);
  1534.     fsize    = temp + (long)(buf_end - current_char);
  1535.     TWVSLpos = (int)((1000L * temp) / fsize);
  1536.  
  1537.     temp    = (long)current.mrow * (long)current.mcol;
  1538.     if (temp > fsize)
  1539.         temp = fsize;
  1540.     TWVSLsize = (int)((1000L * temp) / fsize);
  1541. }
  1542.  
  1543. PiTag_cmd(fpos)
  1544. int    fpos;
  1545. {
  1546.     if (!pi_tag(&fpos))
  1547.         return;
  1548.     if (ptagc(*current_char))        /* if cursor at Pi TAG    */
  1549.         *(current_char+1) = (char)fpos;    /* overwrite old one    */
  1550.     else
  1551.     if (Infsp()) {                /* check insert space    */
  1552.         if (wdw_ptr[cur_line()] == current_char)
  1553.             wdw_ptr[cur_line()] = free_start;
  1554.         *free_start++ = PTAG;        /* insert PTAG + fpos    */
  1555.         *free_start++ = (char)fpos;
  1556.         TWrewindow(current_char);
  1557.     }
  1558.     else    return;
  1559.     TWaltered = true;
  1560.     nscr(3);
  1561. }
  1562.